home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-13  |  19.5 KB  |  623 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: file.c,v 5.20 1993/05/14 03:57:36 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.20 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: file.c,v $
  17.  * Revision 5.20  1993/05/14  03:57:36  syd
  18.  * A couple of calls to want_to() had typos. Here is the patch.
  19.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  20.  *
  21.  * Revision 5.19  1993/05/14  03:53:46  syd
  22.  * Fix wrong message being displayed and then overwritten
  23.  * for long aliases.
  24.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  25.  *
  26.  * Revision 5.18  1993/05/08  20:25:33  syd
  27.  * Add sleepmsg to control transient message delays
  28.  * From: Syd
  29.  *
  30.  * Revision 5.17  1993/05/08  19:26:36  syd
  31.  * Prevent overwriting appended message.
  32.  * From: Jason Molenda <molenda@sequent.com>
  33.  *
  34.  * Revision 5.16  1993/04/12  02:34:36  syd
  35.  * I have now added a parameter which controls whether want_to clears the
  36.  * line and centers the question or behaves like it did before. I also
  37.  * added a 0 at the end of the parameter list to all the other calls to
  38.  * want_to where a centered question on a clean line is not desirable.
  39.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  40.  *
  41.  * Revision 5.15  1993/02/03  17:12:53  syd
  42.  * move more declarations to defs.h, including sleep
  43.  * From: Syd
  44.  *
  45.  * Revision 5.14  1993/01/29  03:40:18  syd
  46.  * back out the change to clear lines-2, its worse than
  47.  * overwriting it.
  48.  * From: Syd
  49.  *
  50.  * Revision 5.13  1993/01/27  20:48:01  syd
  51.  * Change where confirm prompt are written.
  52.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  53.  *
  54.  * Revision 5.12  1993/01/19  05:07:05  syd
  55.  * Trim erroreous extra log entry
  56.  * From: Syd
  57.  *
  58.  * Revision 5.11  1993/01/19  04:55:10  syd
  59.  * fix which file name is used on confirm messages
  60.  * From: vogt@isa.de (Gerald Vogt)
  61.  *
  62.  * Revision 5.10  1993/01/19  04:47:12  syd
  63.  * Significant changes to provide consistent Date and From_ header
  64.  * cracking.  Overhauled date utilities and moved into library.  Moved
  65.  * real_from() into library.  Modified frm, newmail, and readmsg utilities
  66.  * to use library version of real_from().  Moved get_word() from Elm
  67.  * source into library.  Added new library routines atonum() and strfcpy().
  68.  * Fixed trailing backslash bug in len_next().
  69.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  70.  *
  71.  * Revision 5.9  1992/12/25  00:20:32  syd
  72.  * fix variable name
  73.  * From: Syd
  74.  *
  75.  * Revision 5.8  1992/12/24  21:42:01  syd
  76.  * Fix messages and nls messages to match.  Plus use want_to
  77.  * where appropriate.
  78.  * From: Syd, via prompting from Jan Djarv <Jan.Djarv@sa.erisoft.se>
  79.  *
  80.  * Revision 5.7  1992/12/07  02:38:45  syd
  81.  * When ELM is reporting "appending to <foldername>" I never get to see
  82.  * but a flash of light, before the message line has been replaced by a
  83.  * dummy "Messages saved" string.  And if you happen to have mistyped the
  84.  * foldername or the leading '=', you never see the foldername.
  85.  *
  86.  * This fix will change file.c to show either
  87.  *
  88.  *     Message <what> to <foldername>
  89.  *
  90.  * or
  91.  *     <#> messages <what> to <foldername>
  92.  * From: Bo.Asbjorn.Muldbak <bam@jutland.ColumbiaSC.NCR.COM>
  93.  *
  94.  * Revision 5.6  1992/11/26  01:46:26  syd
  95.  * add Decode option to copy_message, convert copy_message to
  96.  * use bit or for options.
  97.  * From: Syd and bjoerns@stud.cs.uit.no (Bjoern Stabell)
  98.  *
  99.  * Revision 5.5  1992/10/30  21:01:49  syd
  100.  * More changes to folder creation confirmation
  101.  * From: Larry Philps <larryp@sco.COM>
  102.  *
  103.  * Revision 5.4  1992/10/24  13:25:41  syd
  104.  * In our global elm.rc I keep the four options as below
  105.  *
  106.  *     confirmappend = OFF    Don't confirm every append to any file.
  107.  *     confirmcreate = ON    Confirm creation of every new file.
  108.  *     confirmfiles = ON    Confirm append to non folder files though.
  109.  *     confirmfolders = ON    In case someone does not want to be asked
  110.  *                 every time when creating a new file try
  111.  *                 to confirm creation of folders though.
  112.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  113.  *
  114.  * Revision 5.3  1992/10/19  16:44:00  syd
  115.  * Make headers before pwd to allow include of stdio to
  116.  * appear first to avoid prototype conflicts
  117.  * From: Syd via news article by Don Watts
  118.  *
  119.  * Revision 5.2  1992/10/11  00:59:39  syd
  120.  * Fix some compiler warnings that I receive compiling Elm on my SVR4
  121.  * machine.
  122.  * From: Tom Moore <tmoore@fievel.DaytonOH.NCR.COM>
  123.  *
  124.  * Revision 5.1  1992/10/03  22:58:40  syd
  125.  * Initial checkin as of 2.4 Release at PL0
  126.  *
  127.  *
  128.  ******************************************************************************/
  129.  
  130. /** File I/O routines, mostly the save to file command...
  131.  
  132. **/
  133.  
  134. #include "headers.h"
  135. #ifdef PWDINSYS
  136. #  include <sys/pwd.h>
  137. #else
  138. #  include <pwd.h>
  139. #endif
  140.  
  141. #include "s_elm.h"
  142. #include <ctype.h>
  143. #include <errno.h>
  144.  
  145. #ifdef BSD
  146. #undef tolower
  147. #endif
  148.  
  149. extern int errno;
  150.  
  151. char *nameof();
  152.  
  153. void save_message();
  154.  
  155. static char copyhelp[VERY_LONG_STRING];
  156. static char savehelp[VERY_LONG_STRING];
  157. static char prev_fold[SLEN];           /* name of previous folder */
  158.  
  159. void
  160. init_helpmsg( msg, action_word, allow_dot )
  161. char    *msg , *action_word ;
  162. int      allow_dot ;
  163. {
  164.     strcpy( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg1,
  165.         "\n\r\n\rYou must specify a file or folder to "));
  166.  
  167.     strcat( msg, action_word );
  168.  
  169.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg2,
  170.         " to.  Several options\n\rare available:\n\r\
  171. \n\r  '!'  will use your incoming mailbox ("));
  172.  
  173.     strcat( msg, defaultfile ) ;
  174.  
  175.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg3,
  176.         ")\n\r  '>'  will use your \"received\" folder ("));
  177.  
  178.     strcat( msg, nameof( recvd_mail ) ) ;
  179.  
  180.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg4,
  181.         ")\n\r  '<'  will use your \"sent\" folder ("));
  182.  
  183.     strcat( msg, nameof( sent_mail ) ) ;
  184.  
  185.     if( allow_dot ) {
  186.         strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg5,
  187.             ")\n\r  '.' will use the previous folder ("));
  188.  
  189.         strcat( msg, nameof(prev_fold));
  190.     }
  191.  
  192.  
  193.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg6,
  194.         ")\n\r  '@alias' will use the default folder for \"alias\"\n\r\n\r\
  195. If you enter a filename elm will use that file.  If the file name begins\n\r\
  196. with a '=', elm will look for the file in your folder directory\n\r\
  197. (your folder directory is "));
  198.  
  199.     strcat( msg, raw_folders ) ;
  200.  
  201.     strcat( msg, ").\n\r\n\r" ) ;
  202.  
  203.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg7,
  204.         "You may use wildcards in the name, exactly as you do in the shell.  If you\n\r\
  205. do this, a list of all matching files or folders will be printed and you\n\r\
  206. will be prompted for another name.  Thus typing '=a*' will print the names\n\r\
  207. of all folders in your folder directory starting with 'a'.  Typing 'b*.c'\n\r\
  208. will print all files in your local directory starting with 'b' and ending\n\r"));
  209.     strcat( msg, catgets(elm_msg_cat, ElmSet, ElmFileHelpmsg8,
  210. "in '.c'.  A star (*) will usually list everything.  See your local shell\n\r\
  211. manual for more information on wildcards.\n\r\
  212. \n\r\
  213. Sometimes elm will help you out by suggesting a name.  If you want to use\n\r\
  214. the suggested name, simply hit return.  If you don't like it, hit your\n\r\
  215. erase or line erase keys.\n\r\
  216. \n\r\
  217. \n\r\
  218. \n\r"));
  219. }
  220.  
  221.  
  222.  
  223. int
  224. save(redraw, silently, delete)
  225. int *redraw, silently, delete;
  226. {
  227.     /** Save all tagged messages + current in a folder.  If no messages
  228.         are tagged, save the current message instead!  This routine
  229.         will return ZERO if the operation failed.
  230.         'redraw' is set to TRUE iff we use the '?' and mess up
  231.         the screen.  Pretty reasonable, eh?  If "silently" is set,
  232.         then don't output the "D" character upon marking for
  233.         deletion...
  234.         If delete is set, then delete the saved messages, else
  235.         we are just copying the messages without deletion.
  236.     **/
  237.  
  238.     register int    tagged = 0, i, oldstat, appending = 0,
  239.             is_ordinary_file, scount = 0;
  240.     int mesgnum;    /* message whose address is used for save-by-name fn */
  241.     char    filename[SLEN], address[LONG_STRING], buffer[LONG_STRING],
  242.         ch, msg_buffer[SLEN], answer;
  243.     FILE *save_file;
  244.  
  245.     oldstat = headers[current-1]->status;    /* remember */
  246.     *redraw = FALSE;
  247.  
  248.     for (i=0; i < message_count; i++) {
  249.       if (ison(headers[i]->status, TAGGED)) {
  250.         if(!tagged)
  251.           mesgnum = i;    /* first tagged msg -  use this one for
  252.                  * save-by-name folder name */
  253.         tagged++;
  254.       }
  255.     }
  256.  
  257.     if (tagged == 0) {
  258.       mesgnum = current-1;    /* use this one for save-by-name folder name */
  259.       tagged = 1;
  260.       setit(headers[current-1]->status, TAGGED);
  261.     }
  262.  
  263.     dprint(4, (debugfile, "%d message%s tagged for saving (save)\n", tagged,
  264.         plural(tagged)));
  265.  
  266. Retry_Save_If_Not_Confirmed:
  267.     while (1) {
  268.       if (tagged == 1)
  269.         PutLine1(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessageTo,
  270.           "%s message to: "), (delete ? cap_save_word : cap_copy_word));
  271.       else
  272.         PutLine1(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessagesTo,
  273.           "%s messages to: "), (delete ? cap_save_word : cap_copy_word));
  274.  
  275.       if (save_by_name) {
  276.         /** build default filename to save to **/
  277.         get_return(address, mesgnum);
  278.         get_return_name(address, buffer, TRUE);
  279.         sprintf(filename, "=%s", buffer);
  280.       }
  281.       else
  282.         filename[0] = '\0';
  283.  
  284.       if (tagged > 1)
  285.         optionally_enter(filename, LINES-2, 19, FALSE, FALSE);
  286.       else    
  287.         optionally_enter(filename, LINES-2, 18, FALSE, FALSE);
  288.   
  289.  
  290.       if (strlen(filename) == 0) {  /** <return> means 'cancel', right? **/
  291.         headers[current-1]->status = oldstat;    /* BACK! */
  292.         return(0);
  293.       }
  294.      
  295.       if (strcmp(filename,"?") == 0) {    /* user asked for help */
  296.         *redraw = TRUE;    /* set the flag so we know what to do later */
  297.         if ( delete )
  298.         {
  299.           if ( !*savehelp )    /* format helpmsg if not yet done */
  300.             init_helpmsg( savehelp, save_word, TRUE ) ;
  301.           ClearScreen();
  302.           (void) printf( savehelp ) ;
  303.         }
  304.         else
  305.         {
  306.           if ( !*copyhelp )    /* format helpmsg if not yet done */
  307.         init_helpmsg( copyhelp, copy_word, TRUE ) ;
  308.           ClearScreen();
  309.           (void) printf( copyhelp ) ;
  310.         }
  311.         continue;
  312.       }
  313.  
  314.       /* was this a wildcard request? */
  315.       if ( has_wildcards( filename ) )
  316.       {
  317.         *redraw = TRUE ;
  318.         list_folders( 4, NULL, filename ) ;
  319.         continue ;
  320.       }
  321.       /* else - got a folder name - check it out */
  322.       if (! expand_filename(filename, TRUE)) {
  323.         dprint(2, (debugfile,
  324.           "Error: Failed on expansion of filename %s (save)\n", 
  325.           filename));
  326.         continue;
  327.       }
  328.  
  329.       is_ordinary_file = strncmp (filename, folders, strlen(folders));
  330.       
  331.       if ((errno = can_open(filename, "a"))) {
  332.         error2(catgets(elm_msg_cat, ElmSet, ElmCannotSaveMessage,
  333.         "Cannot %s message to folder %s!"),
  334.           delete ? save_word:copy_word, filename);
  335.         continue;
  336.       }
  337.       break;    /* got a valid filename */
  338.     }
  339.  
  340.     save_file_stats(filename);
  341.  
  342.     if (access(filename,ACCESS_EXISTS)== 0) {    /* already there!! */
  343.         appending = 1;
  344.         if (confirm_append || (confirm_files && is_ordinary_file)) {
  345.  
  346.             if (is_ordinary_file)
  347.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFilesAppend,
  348.               "Append to an existing file `%s'? (%c/%c) "),
  349.             filename, *def_ans_yes, *def_ans_no);
  350.             else
  351.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFolderAppend,
  352.                   "Append to mail folder `%s'? (%c/%c) "),
  353.             filename, *def_ans_yes, *def_ans_no);
  354.  
  355.             answer = want_to(msg_buffer, *def_ans_no, LINES-1, 1);
  356.  
  357.         if (answer != *def_ans_yes) {
  358.             goto Retry_Save_If_Not_Confirmed;
  359.         }
  360.         }
  361.     }
  362.     else {
  363.             if (confirm_create || (confirm_folders && !is_ordinary_file)) {
  364.  
  365.             if (is_ordinary_file)
  366.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFilesCreate,
  367.               "Create a new file `%s'? (%c/%c) "),
  368.             filename, *def_ans_yes, *def_ans_no);
  369.             else
  370.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFolderCreate,
  371.                   "Create a new mail folder `%s'? (%c/%c) "),
  372.             filename, *def_ans_yes, *def_ans_no);
  373.  
  374.             answer = want_to(msg_buffer, *def_ans_no, LINES-1, 1);
  375.  
  376.         if (answer != *def_ans_yes) {
  377.             goto Retry_Save_If_Not_Confirmed;
  378.         }
  379.         }
  380.     }
  381.       
  382.     dprint(4,(debugfile, "Saving mail to folder '%s'...\n", filename));
  383.  
  384.     /* save this filename for the next time */
  385.     strfcpy(prev_fold, filename, SLEN);
  386.  
  387.     if ((save_file = fopen(filename,"a")) == NULL) {
  388.       dprint(2, (debugfile,
  389.         "Error: couldn't append to specified folder %s (save)\n", 
  390.         filename));
  391.       error1(catgets(elm_msg_cat, ElmSet, ElmCouldntAppendFolder,
  392.         "Couldn't append to folder %s!"), filename);
  393.       headers[current-1]->status = oldstat;    /* BACK! */
  394.       return(0); 
  395.     }
  396.  
  397.     /* if we need a redraw that means index screen no longer present
  398.      * so whatever silently was, now it's true - we can't show those
  399.      * delete markings.
  400.      */
  401.     if(*redraw) silently = TRUE;
  402.  
  403.     for (i=0; i < message_count; i++)     /* save each tagged msg */
  404.       if (headers[i]->status & TAGGED) {
  405.         save_message(i, filename, save_file, (tagged > 1), appending++, 
  406.              silently, delete);
  407.         scount++;
  408.       }
  409.  
  410.     fclose(save_file);
  411.  
  412.     restore_file_stats(filename);
  413.  
  414.     if (tagged == 1 && !appending)
  415.       error2(catgets(elm_msg_cat, ElmSet, ElmMessageSaved,
  416.         "Message %s to %s."), delete ? saved_word: copied_word,
  417.         filename);
  418.     else if (tagged > 1)
  419.       error3(catgets(elm_msg_cat, ElmSet, ElmMessagesSaved,
  420.           "%d messages %s to %s."), scount, 
  421.           delete ? saved_word: copied_word,
  422.           filename);
  423.     return(1);
  424. }
  425.  
  426. void
  427. save_message(number, filename, fd, pause, appending, silently, delete)
  428. int number, pause, appending, silently, delete;
  429. char *filename;
  430. FILE *fd;
  431. {
  432.     /** Save an actual message to a folder.  This is called by 
  433.         "save()" only!  The parameters are the message number,
  434.         and the name and file descriptor of the folder to save to.
  435.         If 'pause' is true, a sleep(sleepmsg) will be done after the
  436.         saved message appears on the screen...
  437.         'appending' is only true if the folder already exists 
  438.         If 'delete' is true, mark the message for deletion.
  439.     **/
  440.  
  441.     register int save_current, is_new;
  442.     
  443.     dprint(4, (debugfile, "\tSaving message %d to folder...\n", number));
  444.  
  445.     save_current = current;
  446.     current = number+1;
  447.  
  448.     /* change status from NEW before copy and reset to what it was
  449.      * so that copy doesn't look new, but we can preserve new status
  450.      * of message in this mailfile. This is important because if
  451.      * user does a resync, we don't want NEW status to be lost.
  452.      * I.e. NEW becomes UNREAD when we "really" leave a mailfile.
  453.      */
  454.     if(is_new = ison(headers[number]->status, NEW))
  455.       clearit(headers[number]->status, NEW);
  456.     copy_message("", fd, CM_UPDATE_STATUS);
  457.     if(is_new)
  458.       setit(headers[number]->status, NEW);
  459.     current = save_current;
  460.  
  461.     if (delete)
  462.       setit(headers[number]->status, DELETED); /* deleted, but ...   */
  463.     clearit(headers[number]->status, TAGGED);  /* not tagged anymore */
  464.  
  465.     if (appending)
  466.       error2(catgets(elm_msg_cat, ElmSet, ElmMessageAppendedFolder,
  467.         "Message %d appended to folder %s."), number+1, filename);
  468.     else
  469.       error3(catgets(elm_msg_cat, ElmSet, ElmMessageSavedFolder,
  470.         "Message %d %s to folder %s."),
  471.          number+1, delete ? saved_word : copied_word, filename);
  472.  
  473.     if (! silently)
  474.       show_new_status(number);    /* update screen, if needed */
  475.  
  476.     if (pause && (!silently) && (!appending))
  477.         if (sleepmsg > 0)
  478.         sleep(sleepmsg);
  479. }
  480.  
  481. int
  482. expand_filename(filename, use_cursor_control)
  483. char *filename;
  484. int use_cursor_control;
  485. {
  486.     /** Expands    ~/    to the current user's home directory
  487.             ~user/    to the home directory of "user"
  488.             =,+,%    to the user's folder's directory
  489.             !    to the user's incoming mailbox
  490.             >    to the user's received folder
  491.             <    to the user's sent folder
  492.             .    to the last folder used 
  493.             @alias    to the default folder directory for "alias"
  494.             shell variables (begun with $)
  495.  
  496.         Side effect: strips off trailing blanks
  497.  
  498.         Returns     1    upon proper expansions
  499.             0    upon failed expansions
  500.      **/
  501.  
  502.     char temp_filename[SLEN], varname[SLEN], env_value[SLEN],
  503.          logname[SLEN], *ptr, *address, *get_alias_address(),
  504.          buffer[LONG_STRING];
  505.     register int iindex;
  506.     int too_long = FALSE;
  507.     struct passwd *pass, *getpwnam();
  508.     char *getenv();
  509.  
  510.     ptr = filename;
  511.     while (*ptr == ' ') ptr++;    /* leading spaces GONE! */
  512.     strcpy(temp_filename, ptr);
  513.  
  514.     /** New stuff - make sure no illegal char as last **/
  515.     /** Strip off any trailing backslashes or blanks **/
  516.  
  517.     ptr = temp_filename + strlen(temp_filename) - 1;
  518.     while (*ptr == '\n' || *ptr == '\r'
  519.            || *ptr == '\\' || *ptr == ' ' || *ptr == '\t') {
  520.         *ptr-- = '\0';
  521.     }
  522.  
  523.     if (temp_filename[0] == '~') {
  524.       if(temp_filename[1] == '/')
  525.         sprintf(filename, "%s%s%s",
  526.           home, (lastch(home) != '/' ? "/" : ""), &temp_filename[2]);
  527.       else {
  528.         for(ptr = &temp_filename[1], iindex = 0; *ptr && *ptr != '/'; ptr++, iindex++)
  529.           logname[iindex] = *ptr;
  530.         logname[iindex] = '\0';
  531.         if((pass = getpwnam(logname)) == NULL) {
  532.           dprint(3,(debugfile, 
  533.               "Error: Can't get home directory for %s (%s)\n",
  534.               logname, "expand_filename"));
  535.           if(use_cursor_control)
  536.         error1(catgets(elm_msg_cat, ElmSet, ElmDontKnowHomeCursor,
  537.             "Don't know what the home directory of \"%s\" is!"),
  538.             logname);
  539.           else
  540.         printf(catgets(elm_msg_cat, ElmSet, ElmDontKnowHomePrintf,
  541.             "\n\rDon't know what the home directory of \"%s\" is!\n\r"),
  542.             logname);
  543.           return(0);
  544.         }
  545.         sprintf(filename, "%s%s", pass->pw_dir, ptr);
  546.       }
  547.  
  548.     }
  549.     else if (temp_filename[0] == '=' || temp_filename[0] == '+' || 
  550.           temp_filename[0] == '%') {
  551.       sprintf(filename, "%s%s%s", folders, 
  552.         (temp_filename[1] != '/' && lastch(folders) != '/')? "/" : "",
  553.           &temp_filename[1]);
  554.     }
  555.     else if  ( temp_filename[0] == '@' ) {
  556.  
  557.       /* try to expand alias */
  558.  
  559.       if ((address = get_alias_address(&(temp_filename[1]),FALSE,&too_long))
  560.            != NULL) {
  561.  
  562.             if (address[0] == '!') {
  563.           /* Refuse group aliases? */
  564.               address[0] = ' ';
  565.         }
  566.  
  567.         /* get filename from address */
  568.         get_return_name(address, buffer, TRUE);
  569.  
  570.         sprintf(filename, "%s%s%s",
  571.           folders, 
  572.           (temp_filename[1] != '/' && lastch(folders) != '/') ? "/" : "", 
  573.           buffer);
  574.       }
  575.           else {
  576.         if ( use_cursor_control )
  577.           error1(catgets(elm_msg_cat, ElmSet, ElmCannotExpand,
  578.              "Cannot expand alias '%s'!\n\r"), &(temp_filename[1]) );
  579.         else
  580.           printf(catgets(elm_msg_cat, ElmSet, ElmCannotExpand,
  581.              "Cannot expand alias '%s'!\n\r"), &(temp_filename[1]) );
  582.         return(0);
  583.       }
  584.     }
  585.     else if (temp_filename[0] == '$') {    /* env variable! */
  586.       for(ptr = &temp_filename[1], iindex = 0; isalnum(*ptr); ptr++, iindex++)
  587.         varname[iindex] = *ptr;
  588.       varname[iindex] = '\0';
  589.  
  590.       env_value[0] = '\0';            /* null string for strlen! */
  591.       if (getenv(varname) != NULL)
  592.         strcpy(env_value, getenv(varname));
  593.  
  594.       if (strlen(env_value) == 0) {
  595.         dprint(3,(debugfile, 
  596.             "Error: Can't expand environment variable $%s (%s)\n",
  597.             varname, "expand_filename"));
  598.         if(use_cursor_control)
  599.           error1(catgets(elm_msg_cat, ElmSet, ElmDontKnowValueCursor,
  600.             "Don't know what the value of $%s is!"), varname);
  601.         else
  602.           printf(catgets(elm_msg_cat, ElmSet, ElmDontKnowValuePrintf,
  603.             "\n\rDon't know what the value of $%s is!\n\r"), varname);
  604.         return(0);
  605.       }
  606.  
  607.       sprintf(filename, "%s%s%s", env_value, 
  608.         (*ptr && *ptr != '/' && lastch(env_value) != '/')? "/" : "", ptr);
  609.  
  610.     } else if (strcmp(temp_filename, "!") == 0) {
  611.       strcpy(filename, defaultfile);
  612.     } else if (strcmp(temp_filename, ">") == 0) {
  613.       strcpy(filename, recvd_mail);
  614.     } else if (strcmp(temp_filename, "<") == 0) {
  615.       strcpy(filename, sent_mail);
  616.     } else if (strcmp(temp_filename, ".") == 0) {
  617.       strcpy(filename, prev_fold);
  618.     } else
  619.       strcpy(filename, temp_filename);
  620.       
  621.     return(1);
  622. }
  623.